/**
 * @File	OnlineController.java
 * @Package	cn.com.ums.plat.controller	
 * 
 * @Version	@Date		@Author	@Brief
 * 0.1		2017-05-17	Conan	新建
 */
package com.plat.controller;

import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;

import com.plat.common.ApplicationSingleton;
import com.plat.common.UmsConfig;
import com.plat.pool.FacadeBase;
import com.plat.pool.LogicFacadeBase;
import com.plat.pool.PassFacadeBase;
import com.plat.pool.LocalFacadeBase;
import com.ums.umsmsg.UmsMsg;
import com.ums.umsmsg.proc.Trans;

/**
 * @Class	OnlineController
 * @Brief	北京银行控制层
 */
public abstract class OnlineController {
	private static Logger log = Logger.getLogger(OnlineController.class);							//log4j日志

	protected static final String ENCODING = "UTF-8";												//编码

	protected static String MSG_DIR_CFG = UmsConfig.getProperty("msg", "cfg.dir");					//报文配置文件路径
	protected String MSG_CFG = "";															//报文配置文件名

	protected ApplicationContext applicationContext = null;											//应用程序
	protected String recognitionCFG = "";															//识别配置文件

	/* 抽象方法 */
	protected abstract boolean judgeReqAdd(HttpServletRequest request);								//判断是否是合法的请求地址
	protected abstract boolean judgeReqMsg(byte[] msg);												//判断是否是合法的请求报文
	protected abstract byte[] getErrorMsg(String errorCode, String errorMsg);
	protected abstract byte[] getReqMsg(String msg);
		
	/**
	 * @Func	run
	 * @Brief	运行
	 */
	public void run (
			String reqMsg,
			HttpServletRequest request,
			HttpServletResponse response
	) {
		byte[] inMsg = null;
		byte[] outMsg = null;
		Trans trans = null;

		/* 1.判断请求合法性 */
		if(!isLegalReqAdd(request)) {
			log.error("无效IP！");
			outMsg = getErrorMsg("", "无效IP！");
			setRspMsg(response, outMsg);
			return ;
		}

		/* 2.获取请求报文 */
		inMsg = getReqMsg(reqMsg);
		if(inMsg == null || inMsg.length == 0) {
			log.error("请求报文异常！");
			outMsg = getErrorMsg("", "请求报文异常！");
			setRspMsg(response, outMsg);
			return ;
		}

		/* 3.交易识别 */
		trans = recognTrans(inMsg);
		
		/* 4.调用线程异步处理 */
		if(trans != null) {
			outMsg = handle(trans, inMsg);
		} else {
			log.error("无效交易请求！");
			outMsg = getErrorMsg("", "无效交易请求！");
			setRspMsg(response, outMsg);
			return ;
		}		
		
		/* 5.发送返回报文 */
		if(outMsg == null) {
			outMsg = getErrorMsg("", "系统异常！");			
		}
		setRspMsg(response, outMsg);
	}
	
	/**
	 * @Func	isLegalReqAdd
	 * @Brief	是否合法报文
	 */
	private boolean isLegalReqAdd(HttpServletRequest req) {
		log.info("收到IP[" + req.getRemoteAddr() + "]的交易请求...");
		
		boolean is = judgeReqAdd(req);
		if(is) {
			log.info("IP地址合法！");
		} else {
			log.error("IP地址非法！");			
		}
		return is;
	}
	
	/**
	 * @Func	isLegalReqMsg
	 * @Brief	是否合法报文
	 */
	protected boolean isLegalReqMsg(byte[] msg) {
		boolean is = judgeReqMsg(msg);
		if(is) {
			log.info("请求报文合法！");
		} else {
			log.error("请求报文非法！");			
		}
		return is;
	}
	
	/**
	 * @Func	recognTrans
	 * @Brief	请求报文识别
	 */
	private Trans recognTrans(byte[] msg) {
		try {
			log.info("@@@@识别交易路径："+MSG_DIR_CFG+("/".equals(MSG_DIR_CFG.substring(MSG_DIR_CFG.length() - 1)) ? "" : "/")+ MSG_CFG);
			return UmsMsg.recognTrans(
					MSG_DIR_CFG
					+ ("/".equals(MSG_DIR_CFG.substring(MSG_DIR_CFG.length() - 1)) ? "" : "/")
					+ MSG_CFG, 
					msg);
			
		} catch (Exception e) {
			log.error("识别交易出错："+e);
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * @Func	handle
	 * @Brief	请求报文识别
	 */
	private byte[] handle(Trans trans, byte[] reqMsg) {
		applicationContext = ApplicationSingleton.getApplicationContext();

		FacadeBase facadeBase = null;
		Object object = null;
		
		try {
			object = applicationContext.getBean(trans.getRouter(Trans.IN));
		} catch (Exception e) {
			e.printStackTrace() ;
			return getErrorMsg("", "未找到对应的应用处理逻辑！");
		}
				
		if (object == null) {
			log.error("无法获取对应的处理逻辑，请检查！请求路由=[" + trans.getRouter(Trans.IN) + "]");
			return null;
		}else{
			/* 逻辑类交易 */
			if (object instanceof LogicFacadeBase) {
				facadeBase = (LogicFacadeBase) object;
			/* 透传类交易 */
			} else if(object instanceof PassFacadeBase) {
				facadeBase = (PassFacadeBase) object;
			/* 本地类交易 */
			} else if(object instanceof LocalFacadeBase) {
				facadeBase = (LocalFacadeBase) object;
			}
			
			try {
				facadeBase.setApplicationContext(applicationContext);
				facadeBase.setReqMessage(reqMsg);
				facadeBase.setTrans(trans);
				facadeBase.run();
				
				return facadeBase.getRspMessage();				
			} catch (Exception e) {
				log.error("facadeBase.run() occur error :"+e);
				e.printStackTrace();
				return getErrorMsg("", "业务应用处理异常！");
			}

		}		
	}
	
	/**
	 * @Func	setRspMsg
	 * @Brief	设置发送报文
	 */
	private void setRspMsg(HttpServletResponse rsp, byte[] msg) {
		try {
			rsp.setContentType("application/json;charset=" + ENCODING);
			rsp.getWriter().write(new String(msg));
		} catch (IOException e) {
			log.error("写返回报文失败：" + e);
			e.printStackTrace();
		}
	}
}
